﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Tutorial.Domain;

namespace TestByWire.Tutorial
{
    [TestClass]
    [UseStub(typeof(IEventRaiser), typeof(MyEventRaiser))]
	[UseStubLateBound(typeof(IEmployeStorage), "_adStorage")]
    [UseStubLateBound(typeof(IEmployeStorage),"_database")]
    [UseStubLateBound(typeof(ITaxationCalulator), "_taxCalc", typeof(MyTaxCalculator))]
    public class PullingItAllTogether : TestTarget<TonOfTrouble>
    {
        [TestMethod]
        public void EventRaiserIsStubbed()
        {
            When.Calling.DoNothing();
            // Der er registreret en proxy af min stub
            Then<IEventRaiser>.Fulfills(x => x.GetType() == typeof(MyEventRaiser));
        }

        [TestMethod]
        public void FailIfNotStubbed()
        {
            When.Calling.FailsIfTargetIsNotStubbed(typeof(MyEventRaiser));
        }

        [TestMethod]
        public void AdStorageHasStubOnName()
        {
            When.Calling.DoNothing();

            Then<IEmployeStorage>.Fulfills("_adStorage", x => x.GetType() != typeof(MyAdStorage));
        }

        [TestMethod]
        public void DatabaseHasStubOnName()
        {
            When.Calling.DoNothing();

            Then<IEmployeStorage>.Fulfills("_database", x => x.GetType() != typeof(MyDatabase));
        }

        [TestMethod]
        public void TaxCalculatorIsStubbedOnNameAlways()
        {
            When.Calling.DoNothing();
            // Der er ikke registreret noget på dette interface.
			Then<ITaxationCalulator>.Fulfills("_taxCalc", x => x.GetType() == typeof(MyTaxCalculator));
        }

        [TestMethod]
        public void SalaryIndexIsInjected()
        {
            When.Calling.DoNothing();

            Then<ISalaryIndex>.Fulfills(x => x != null);
        }
    }

    public class MyTaxCalculator : ITaxationCalulator
    {
        public double CalculateTax(double saleryAdjustment)
        {
            throw new NotImplementedException();
        }
    }


    public class MyEventRaiser : IEventRaiser
    {
        public event EventHandler<StringEventArgs> eventToRaise;
    }

    public class TonOfTrouble
    {
        private readonly ISalaryIndex _salaryIndex;
        private readonly IEventRaiser _eventRaiser;
        private IEmployeStorage _adStorage;
        private IEmployeStorage _database;
        private ITaxationCalulator _taxCalc;

        public TonOfTrouble(ISalaryIndex salaryIndex, IEventRaiser eventRaiser)
        {
            _salaryIndex = salaryIndex;
            _eventRaiser = eventRaiser;
            _adStorage = new MyAdStorage();
            _database = new MyDatabase();
            _taxCalc = null;
        }

        public void DoNothing()
        {
            
        }

        public void FailsIfTargetIsNotStubbed(Type expectedStub)
        {
            if (expectedStub != _eventRaiser.GetType())
                throw new InvalidOperationException(String.Format("Expected stub of type: {0}, but was: {1}", expectedStub,
                                                              _eventRaiser.GetType()));
        }
    }

    public class MyDatabase : IEmployeStorage
    {
        public EmployeInformation RetrieveCurrentSalary(string employeeId)
        {
            throw new NotImplementedException();
        }

        public void UpdateSalary(EmployeInformation employeInformation, double newSalary)
        {
            throw new NotImplementedException();
        }
    }

    public class MyAdStorage : IEmployeStorage
    {
        public EmployeInformation RetrieveCurrentSalary(string employeeId)
        {
            throw new NotImplementedException();
        }

        public void UpdateSalary(EmployeInformation employeInformation, double newSalary)
        {
            throw new NotImplementedException();
        }
    }

}
